package mahjong;

import org.junit.*;

import static org.junit.Assert.*;

public class Milestone2Test {

	private Board testBoard;
	private Tile[] testTiles;
	private Viewer testViewer;
	private Player testPlayer;
	private HighScoreList hsl;
	private HighScores testHS;
	
	@Before
	public void setUp()
	{
		String boardName = "Layouts"+ java.io.File.separator + "test.layout";
		testBoard =  new Board(boardName);
		testTiles = testBoard.getContent();
		testPlayer = new Player();
		testViewer = new Viewer(testBoard, testPlayer ); 
		testPlayer.setBoard(testBoard);
		testPlayer.setView(testViewer);
		hsl = new HighScoreList("jUnitTest");
	}
	
	/*
	 * Test the redo undo feature
	 */
	@Test
	public void testUndoRedo()
	{
		//remove tile 0 and 1
		testBoard.makeMove(testTiles[0]);
		testBoard.makeMove(testTiles[1]);
		// hit undo
		testBoard.undo();
		//check if removed tiles are back on play
		assertFalse(testTiles[0].isRemoved());
		assertFalse(testTiles[1].isRemoved());
		// hit redo
		testBoard.redo();
		//check if tiles are removed once more
		assertTrue(testTiles[0].isRemoved());
		assertTrue(testTiles[1].isRemoved());	
		//reset the board
		testBoard.reset();
	}
	
	@Test
	public void testLoadSave()
	{
		//remove tile 0 and 1
		testBoard.makeMove(testTiles[0]);
		testBoard.makeMove(testTiles[1]);
		//save the game
		//reset board
		testBoard.reset();
		//load Board
		
	}
	
	/*
	 * Test Score compareTo
	 */
	@Test
	public void testScore()
	{
		//10 should be < than 11
		Score a = new Score("a",10);
		Score b = new Score("b" ,11);
		assertTrue(a.compareTo(b) < 0);
	}
	
	@Test
	public void testGameTime()
	{
		//test time format
		assertTrue(TimeFormater.formatTime(90).equals("00:01:30"));
		
		//set GameTime
		GameTime.setTime(127);
		//test both time int and time String from 127 value
		assertTrue(GameTime.timeToInt() == 127);
		assertTrue(GameTime.getTimeString().equals("00:02:07"));
	
		//test add second
		GameTime.setTime(0);
		GameTime.addSecond();
		assertTrue(GameTime.timeToInt()==1);
		//test time reset
		GameTime.setTime(100);
		assertFalse(GameTime.timeToInt() == 0);
		GameTime.resetTimer();
		assertTrue(GameTime.timeToInt() == 0);
	
	}
	/*
	 * Test adding HighScores
	 */
	@Test
	public void testAddHighScore()
	{
		assertTrue(hsl.getHighScores().equals("No highscores for this layout!"));
		//generate 10 scores at 10 seconds
		for(int i = 0; i<10; i++)
		{
			hsl.addHighScore(new Score("tester",10));
		}
		//make sure High Score list is not empty
		assertFalse(hsl.getHighScores().equals("No highscores for this layout!"));
		//make sure you can add a score of 9 seconds
		assertTrue(hsl.canAdd(9));
		//make sure you can't add a time of 11 seconds
		assertFalse(hsl.canAdd(11));
				
	}
	/*
	 * Test timer start stop
	 */
	@Test
	public void testTimerSS()
	{
		GameTime.setTime(0);
		GameTime.startTimer();
		try
		{
			Thread.sleep(1500);//sleep for 1500 ms
			int currTime = GameTime.timeToInt();
			GameTime.stopTimer();
			//check that time has passed
			assertFalse( currTime == 0);
			Thread.sleep(1500);//sleep for 1500 ms
			//check that time has not passed
			assertTrue(currTime == GameTime.timeToInt());		  
		}
		catch(InterruptedException ie)
		{
			System.out.println(ie);
		}
		
	}
	
	/*
	 * Test hints
	 * 
	 */
	@Test
	public void testHS(){
		
		//make sure all tiles are in play
		for(int i = 0; i < 4; i++)
		{
			testTiles[i].addToPlay();
		}
		//turn hintmode on
		testViewer.switchHintMode();
		//see if tiles are hinted
		for(int i = 0; i < 4; i++)
		{
			assertTrue(testTiles[i].returnHint() == 1);
		}
		//turn hint mode off
		testViewer.switchHintMode();
		//check that tiles arent hinted
		for(int i = 0; i < 4; i++)
		{
			assertTrue(testTiles[i].returnHint() == 0);
		}
		//make all tiles the same
		for(int i = 0; i < 4; i++)
		{
			testTiles[i].setValue(1);
		}
		//turn hint mode on
		testViewer.switchHintMode();
		//check if all tiles are 4 hinted
		for(int i = 0; i < 4; i++)
		{
			assertTrue(testTiles[i].returnHint() == 2);
		}
		//toggle hint mode back off
		testViewer.switchHintMode();
	}
	/*
	 * Test solvability
	 */
	@Test
	public void testSolvability()
	{
		
		String tBoardName = "Layouts"+ java.io.File.separator + "turtle.layout";
		Board tBoard =  new Board(tBoardName);
		String zBoardName = "Layouts"+ java.io.File.separator + "ziggurat.layout";
		Board zBoard =  new Board(zBoardName);
		
		//generate and solve 2 board layouts 1000 times each
		for(int i = 0; i <1000; i++)
		{
			tBoard.testSolvability();
			assertTrue(tBoard.isEmpty());
			zBoard.testSolvability();
			assertTrue(zBoard.isEmpty());
			//rebuild boards
			tBoard.build(null); // null will generate a new seed
			zBoard.build(null);
			//make sure board have been rebuilt
			assertFalse(tBoard.isEmpty());
			assertFalse(zBoard.isEmpty());
		}
		
	}
	
}
